package org.rainwalk.library.controller;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import lombok.RequiredArgsConstructor;
import org.rainwalk.library.api.auth.Auth;
import org.rainwalk.library.api.exception.BizException;
import org.rainwalk.library.api.log.ApiLog;
import org.rainwalk.library.api.model.Response;
import org.rainwalk.library.api.model.ResponseCode;
import org.rainwalk.library.entity.Storage;
import org.rainwalk.library.model.dto.FileAddDTO;
import org.rainwalk.library.model.enums.ContentType;
import org.rainwalk.library.model.enums.FileType;
import org.rainwalk.library.model.vo.FileOpenVO;
import org.rainwalk.library.model.vo.LibrarySearchVO;
import org.rainwalk.library.model.vo.StorageVO;
import org.rainwalk.library.service.ILibraryService;
import org.rainwalk.library.service.IStorageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 文件相关接口
 *
 * @author 趁雨行 2021/7/7
 */
@RestController
@RequestMapping("/file")
@RequiredArgsConstructor(onConstructor_={@Autowired})
public class FileController {

    private final IStorageService storageService;

    private final ILibraryService libraryService;

    @Auth
    @ApiLog("上传文件")
    @PostMapping
    public Response add(@Validated FileAddDTO fileAddDTO) {
        String suffix = FileUtil.getSuffix(fileAddDTO.getFile().getOriginalFilename());
        FileType fileType = FileType.getByDesc(suffix);
        if (fileType == null) {
            String fileTypeValues = Arrays.stream(FileType.values()).map(FileType::getValue).collect(Collectors.joining("，"));
            return Response.fail(ResponseCode.PARAMS_VERITY_FAIL, String.format("只支持%s文件格式", fileTypeValues));
        }
        StorageVO storageVO = storageService.addFile(fileAddDTO, fileType);
        if (storageVO == null) {
            return Response.fail(ResponseCode.PARAMS_VERITY_FAIL, "上传文件失败");
        }
        return Response.success(storageVO);
    }

    @ApiLog("打开文件")
    @GetMapping("/{id}/{filename}")
    public void open(@PathVariable Long id, HttpServletResponse response, @PathVariable String filename) {
        FileOpenVO fileOpenVO = storageService.getFile(id);
        ContentType contentType = ContentType.getByType(fileOpenVO.getType());
        if (contentType == null) {
            throw new BizException(ResponseCode.SERVER_ERROR, "文件类型有误");
        }

        try (ServletOutputStream os = response.getOutputStream();
             FileInputStream is = new FileInputStream(fileOpenVO.getFile())){
            response.setContentType(contentType.getValue());
            IoUtil.copy(is, os);
        } catch (IOException e) {
            throw new BizException(ResponseCode.SERVER_ERROR, "打开文件失败");
        }
    }

    /**
     * 全文检索
     *
     * @param keyword 关键字
     */
    @GetMapping
    public Response search(@RequestParam String keyword) {
        List<LibrarySearchVO> result;
        try {
            result = libraryService.search(keyword);
        } catch (IOException e) {
            return Response.error();
        }

        Iterator<LibrarySearchVO> iterator = result.iterator();
        while (iterator.hasNext()) {
            LibrarySearchVO vo = iterator.next();
            Long id = vo.getId();
            Storage storage = storageService.getById(id);
            if (storage == null) {
                //文件已删除但es索引未删除，删除改结果
                iterator.remove();
                continue;
            }
            vo.setTitle(storage.getTitle());
            vo.setFileType(storage.getFileType());
        }

        return Response.success(result);
    }
}
